/*!
 * Destroy a stream.
 * https://github.com/stream-utils/destroy/blob/master/index.js
 */

import { EventEmitter } from 'node:events'
import { ReadStream } from 'node:fs'
import Stream from 'node:stream'
import Zlib from 'node:zlib'

/**
 * Destroy the given stream, and optionally suppress any future `error` events.
 *
 * @param {object} stream
 * @param {boolean} suppress
 */
export default function destroyStream(stream, suppress) {
  if(stream instanceof ReadStream) {
    destroyReadStream(stream)
  } else if(isZlibStream(stream)) {
    stream.close()
  } else if(stream instanceof Stream) {
    if(typeof stream.destroy === 'function') {
      stream.destroy()
    }
  }

  if(stream instanceof EventEmitter && suppress) {
    stream.removeAllListeners('error')
    stream.addListener('error', noop)
  }

  return stream
}

/**
 * Destroy a ReadStream.
 *
 * @param {object} stream
 */
function destroyReadStream(stream) {
  stream.destroy()

  if(typeof stream.close === 'function') {
    // node.js core bug work-around
    stream.on('open', onOpenClose)
  }
}

/**
 * Determine if stream is Zlib stream.
 */
function isZlibStream(stream) {
  return stream instanceof Zlib.Gzip ||
    stream instanceof Zlib.Gunzip ||
    stream instanceof Zlib.Deflate ||
    stream instanceof Zlib.DeflateRaw ||
    stream instanceof Zlib.Inflate ||
    stream instanceof Zlib.InflateRaw ||
    stream instanceof Zlib.Unzip
}

/**
 * No-op function.
 */
function noop() {}

/**
 * On open handler to close stream.
 */
function onOpenClose() {
  if(typeof this.fd === 'number') {
    // actually close down the fd
    this.close()
  }
}
